package encaps.action;

import encaps.entities.*;
import encaps.logging.JMSUtil;
import encaps.logging.Log;
import encaps.resources.Config;
import encaps.resources.Labels;
import encaps.utils.*;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import javax.naming.NamingException;
import org.jdom.Element;

public class ApplyMovieChangesAction extends Action {

    public static final String APPLY_MOVIE_CHANGES = "applyMovieChanges";
    public static final String MOVIE_TITLE = "movieTitle";
    public static final String MOVIE_DESCRIPTION = "movieDescription";
    public static final String MOVIE_LENGTH = "movieLength";
    public static final String MOVIE_COUNTRIES = "countries";
    public static final String MOVIE_RATING = "movieRating";
    public static final String MOVIE_RUSRELEASEDATE = "movieRusRelDate";
    public static final String MOVIE_WLDRELEASEDATE = "movieWorldRelDate";
    public static final String MOVIE_PICTURE = "moviePicture";
    public static final String MOVIE_STUDIO = "movieStudio";
    public static final String MOVIE_GENRES = "movieGenres";
    public static final String MOVIE_CASH = "movieCash";
    public static final String MOVIE_BUDGET = "movieBudget";
    public static final String MOVIE_PERSONS_ACTORS = "actors";
    public static final String MOVIE_PERSONS_DIRECTORS = "directors";
    public static final String MOVIE_PERSONS_PRODUCERS = "producers";
    protected ActionContext actionContext;
    protected String successActionMessage;
    protected boolean edit;
    private Long id;
    private String persons_actors;
    private String persons_directors;
    private String persons_producers;
    private String title;
    private String descript;
    private Integer length;
    private String countries;
    private Date russianReleaseDate;
    private Date worldReleaseDate;
    private String studio;
    private Integer budget;
    private Integer worldCash;
    private HashSet genres;
    private String picture;

    public ApplyMovieChangesAction(ActionContext context, Grant requiredGrant) {
        this.actionContext = context;
        this.requiredGrant = requiredGrant;
        successActionMessage = Labels.getLabel(Labels.MOVIE_CHANGED_MESSAGE);
        edit = false;
    }

    @Override
    public Element execute() throws ActionExecutionException {
        try {
            MovieLocalHome movieHome = EntityUtil.getMovieHome();
            MovieLocal movie;
            id = new Long(actionContext.getTextParameter(ID));

            title = actionContext.getTextParameter(MOVIE_TITLE);
            descript = actionContext.getTextParameter(MOVIE_DESCRIPTION);
            countries = actionContext.getTextParameter(MOVIE_COUNTRIES);
            studio = actionContext.getTextParameter(MOVIE_STUDIO);
            picture = actionContext.getTextParameter(MOVIE_PICTURE);
            persons_actors = actionContext.getTextParameter(MOVIE_PERSONS_ACTORS);
            persons_directors = actionContext.getTextParameter(MOVIE_PERSONS_DIRECTORS);
            persons_producers = actionContext.getTextParameter(MOVIE_PERSONS_PRODUCERS);

            Map<String, String> validationMessages = validate();

            if (!validationMessages.isEmpty()) {
                movie = new ShowEmptyMoviePageAction.DefaultMovieFields(id);
                String pic = movieHome.findByPrimaryKey(id).getPicture();
                movie.setPicture(pic);
            } else {
                if (id.equals(0l)) {
                    movie = movieHome.create(title, "", null,
                            new HashSet(), new HashSet(), new Date(0l), new Date(0l),
                            null, null, 0, 0, 0);
                } else {
                    movie = movieHome.findByPrimaryKey(id);
                    movie.setTitle(title);
                    movie.setDescription(descript);
                    movie.setCountries(countries);
                    movie.setStudio(studio);
                }
            }

            movie.setTitle(title);
            movie.setDescription(descript);
            movie.setCountries(countries);
            movie.setStudio(studio);
            movie.setBudget(budget);
            movie.setWorldCash(worldCash);
            movie.setLength(length);
            movie.setRussianReleaseDate(russianReleaseDate);
            movie.setWorldReleaseDate(worldReleaseDate);
            movie.setPersons(personsParser());
            movie.setGenres(genres);

            String username = actionContext.getUserLogin();

            if (validationMessages.isEmpty()) {
                String picName = String.format("%d-%s", movie.getId(), ""); // actionContext.getTextParameter(picture file name);
                String picPath = IOHelper.uploadFile(actionContext, Labels.MOVIE_PICTURE, picName, Config.getMovieImagesDirectory());

                if (picPath != null) {
                    movie.setPicture(picPath);
                }

                Long uid = EntityUtil.getUserHome().findByLogin(username).getID();
                JMSUtil.sendLogMessage(Log.INSERT, uid, username, new Date(),
                        Movie.TABLE_NAME, movie.getId(), movie.getTitle());
                //Убрать?..
                return XMLHelper.createTextMessage(successActionMessage);
            } ///////////////////////////////////////
            ///////////////////////////////////////
            else {
                return XMLHelper.toXMLElement(movie,
                        Labels.getLabel(Labels.VIEW_MOVIE), true, username,
                        actionContext.getUserRole(), validationMessages);
            }
        } catch (SystemException ex) {
            throw new ActionExecutionException("Cannot execute action", ex);
        } catch (FinderException ex) {
            throw new ActionExecutionException("Cannot execute action", ex);
        } catch (NamingException ex) {
            throw new ActionExecutionException("Cannot execute action", ex);
        } catch (CreateException ex) {
            throw new ActionExecutionException("Cannot execute action", ex);
        }

    }

    private Map<String, String> validate() throws SystemException {
        Map<String, String> messages = new HashMap<String, String>();

        if (StringUtil.isEmpty(title)) {
            messages.put(MOVIE_TITLE, Labels.getLabel(Labels.EMPTY_TITLE_FIELD_MESSAGE));
        }

        try {
            String lengthString = actionContext.getTextParameter(MOVIE_LENGTH);
            length = TypeConverter.convertToInt(lengthString);
        } catch (ConversionException ex) {
            messages.put(MOVIE_LENGTH, Labels.getLabel(Labels.INVALID_NUMERIC_VALUE_MESSAGE));
            length = null;
        }

        try {
            String russianReleaseDateString = actionContext.getTextParameter(MOVIE_RUSRELEASEDATE);
            russianReleaseDate = TypeConverter.convertToDate(russianReleaseDateString);
        } catch (ConversionException ex) {
            messages.put(MOVIE_RUSRELEASEDATE, Labels.getLabel(Labels.INVALID_DATE_FORMAT));
            russianReleaseDate = null;
        }

        try {
            String worldReleaseDateString = actionContext.getTextParameter(MOVIE_WLDRELEASEDATE);
            worldReleaseDate = TypeConverter.convertToDate(worldReleaseDateString);
        } catch (ConversionException ex) {
            messages.put(MOVIE_WLDRELEASEDATE, Labels.getLabel(Labels.INVALID_DATE_FORMAT));
            worldReleaseDate = null;
        }

        try {
            String budgetString = actionContext.getTextParameter(MOVIE_BUDGET);
            budget = TypeConverter.convertToInt(budgetString);
        } catch (ConversionException ex) {
            messages.put(MOVIE_BUDGET, Labels.getLabel(Labels.INVALID_NUMERIC_VALUE_MESSAGE));
            budget = null;
        }

        try {
            String worldCashString = actionContext.getTextParameter(MOVIE_CASH);
            worldCash = TypeConverter.convertToInt(worldCashString);
        } catch (ConversionException ex) {
            messages.put(MOVIE_CASH, Labels.getLabel(Labels.INVALID_NUMERIC_VALUE_MESSAGE));
            worldCash = null;
        }

        try {
            String genresString = actionContext.getTextParameter(MOVIE_GENRES);
            String[] s = genresString.split(";");
            genres = new HashSet();
            String g = Provider.getUniqueString(RoleGrantGenreEnum.GENRE);
            for (String mg : s) {
                if (!mg.isEmpty()) {
                    if (g.contains(mg)) {
                        genres.add(mg);
                    }
                }
            }
        } catch (SQLException ex) {
            messages.put(MOVIE_GENRES, Labels.getLabel(Labels.INVALID_NUMERIC_VALUE_MESSAGE));
            genres = null;
        } catch (NamingException ex) {
            messages.put(MOVIE_GENRES, Labels.getLabel(Labels.INVALID_NUMERIC_VALUE_MESSAGE));
            genres = null;
        }


        return messages;
    }

    private HashSet personsParser() throws ActionExecutionException {

        HashSet p = new HashSet();
        try {
            MoviePersonInfo mp;
            String[] actors = persons_actors.split(";");
            for (String str : actors) {
                if (!str.isEmpty()) {
                    mp = new MoviePersonInfo();
                    mp.id = Long.valueOf(str);
                    mp.type = MoviePersonInfo.ACTOR;
                    p.add(mp);
                }
            }
            String[] producers = persons_producers.split(";");
            for (String str : producers) {
                if (!str.isEmpty()) {
                    mp = new MoviePersonInfo();
                    mp.id = Long.valueOf(str);
                    mp.type = MoviePersonInfo.PRODUCER;
                    p.add(mp);
                }
            }

            String[] directors = persons_directors.split(";");

            for (String str : directors) {
                if (!str.isEmpty()) {
                    mp = new MoviePersonInfo();
                    mp.id = Long.valueOf(str);
                    mp.type = MoviePersonInfo.DIRECTOR;
                    p.add(mp);
                }
            }
        } catch (NumberFormatException ed) {
            throw new ActionExecutionException("Cannot execute action " + persons_actors + "!" + persons_producers + "!" + persons_directors, ed);
        }
        return p;
    }
}
